﻿using System;
using System.Collections.ObjectModel;
using System.Data.Services.Client;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
using Client.ExampleServiceReference;
using Client.ExampleServiceReference2;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            const string sURI = "http://localhost:37052/ExampleDataService.svc";
            const string sURI2 = "http://localhost:37052/ExampleDataService2.svc";

            try
            {
                var proxy = new AdventureWorksEntities(new Uri(sURI));
                var proxy2 = new BusinessEntities(new Uri(sURI2)) 
                    {MergeOption = MergeOption.OverwriteChanges};

                var Redo = "";
                while (Redo != null && Redo.ToLower() != "end")
                {
                    Console.Clear();
                    Console.WriteLine("Enter 'Create', 'Read', 'Update', 'Delete' or 'End' :");

                    //JDO: Depending on the choice do one of the CRUD operations                    
                    switch (Redo.ToUpper())
                    {
                        case "CREATE":
                            Create(proxy2);
                            break;

                        case "READ":
                            Read(proxy, proxy2);
                            break;

                        case "UPDATE":
                            Update(proxy2);
                            break;

                        case "DELETE":
                            Delete(proxy2);
                            break;
                    }

                    Redo = Console.ReadLine();
                }
            }
            catch (CommunicationException ce)
            {
                Console.WriteLine("Error: {0}", ce.Message);
            }
        }

        #region Create Implementation
        static private void Create(BusinessEntities proxy)
        {
            Console.WriteLine("### CREATE ###");

            //JDO: Get a local store for the Thirdparties
            var ThpLocal = (from t in proxy.Thirdparties                             
                             select t).ToList();
            
            //JDO: Either get the next ThirdParty ID or use ID == 1
            var newThpID = 1;
            if (ThpLocal.Count > 0)
                newThpID += (from t in ThpLocal
                             select t.ID).Max();

            //JDO: Add a newly generated Thirdparty to the Thirdparty Store
            var newThirdparty = new Thirdparty() { ID = newThpID, Name = "CREATED" };
            proxy.AddToThirdparties(newThirdparty);

            //JDO: Get a local store for the InvoiceLines
            var InvoiceLinesLocal = (from il in proxy.InvoiceLines                                     
                                     select il).ToList();

            //JDO: Either get the next InvoiceLine ID or use ID == 1
            var newLineID = 1;
            if (InvoiceLinesLocal.Count > 0)
                newLineID += (from il in InvoiceLinesLocal
                             select il.ID).Max();

            //JDO: Add newly generated InvoiceLines to the InvoiceLine Store
            var newInvoiceLines = new Collection<InvoiceLine>();
            var newInvoiceLine1 = new InvoiceLine() { ID = newLineID, Quantity = 6, UnitValue = 30 };
            proxy.AddToInvoiceLines(newInvoiceLine1);
            newInvoiceLines.Add(newInvoiceLine1);
            var newInvoiceLine2 = new InvoiceLine() { ID = ++newLineID, Quantity = 6, UnitValue = 30 };
            proxy.AddToInvoiceLines(newInvoiceLine2);
            newInvoiceLines.Add(newInvoiceLine2);

            //JDO: Get a local store for the Invoices
            var InvoicesLocal = (from inv in proxy.Invoices
                                     select inv).ToList();

            //JDO: Either get the next Invoice ID or use ID == 1
            var newInvoiceID = 1;
            if (InvoicesLocal.Count > 0)
                newInvoiceID += (from inv in InvoicesLocal                                     
                                     select inv.ID).Max();

            //JDO: Add newly generated Invoice to the Invoice Store
            var newInvoice = new Invoice() { dateInvoice = DateTime.Now, ID = newInvoiceID };
            proxy.AddToInvoices(newInvoice);

            //JDO: Link the new Thirdpaty and the new InvoiceLines to the Invoice
            proxy.SetLink(newInvoice, "thirdParty", newThirdparty);
            newInvoice.invoiceLines = new Collection<InvoiceLine>();
            foreach (var invoiceLine in newInvoiceLines)
            {
                proxy.AddLink(newInvoice, "invoiceLines", invoiceLine);
            }

            //JDO: Save the changes using a single call to the Data Service (Batch)
            proxy.SaveChanges(SaveChangesOptions.Batch);

            //JDO: Display information about the created objects in the console
            Console.WriteLine("Thirdparty " + newThirdparty.ID + " was created.");
            Console.WriteLine("InvoiceLines " + newInvoiceLine1.ID + " and " + newInvoiceLine2.ID + " were created.");
            Console.WriteLine("Invoice " + newInvoice.ID + " was created.");
        }
        #endregion

        #region Read Implementation
        static private void Read(AdventureWorksEntities proxy, BusinessEntities proxy2)
        {
            Console.WriteLine("### READ ###");
            Console.WriteLine("Enter 'EF' or 'Custom' :");
            var mode = Console.ReadLine();

            //JDO: Depending on the choice either use the EF or the Custom Data Service
            if (mode!= null && mode.ToUpper() == "EF")
            {
                ReadEF(proxy);
            }
            else if (mode != null && mode.ToUpper() == "CUSTOM")
            {
                ReadCustom(proxy2);
            }
        }

        static private void ReadEF(AdventureWorksEntities proxy)
        {
            //JDO: Get all Products
            var query = from p in proxy.Product
                        orderby p.Name
                        select p;

            //JDO: Display some example data in the console
            foreach (var prod in query)
            {
                Console.WriteLine("Product Name:" + prod.Name + "\n");
            }
        }

        static private void ReadCustom(BusinessEntities proxy)
        {
            //JDO: Get all Invoices and their nested Thirdparty and Invoicelines elements
            var query = from i in proxy.Invoices.Expand("thirdParty").Expand("invoiceLines")
                        select i;

            //JDO: Display some example data in the console
            foreach (var invoice in query)
            {
                Console.WriteLine("InvoiceID: " + invoice.ID + ", Thirdparty: " + invoice.thirdParty.Name + "\n");
                var Total = new decimal();
                foreach (var line in invoice.invoiceLines)
                {
                    Console.WriteLine("\tID: " + line.ID + ", Qte: " + line.Quantity + ", Price: " + line.UnitValue + "\n");
                    Total += line.Quantity * line.UnitValue;
                }
                Console.WriteLine("Total Price: " + Total + "\n");
            }
        }
        #endregion

        #region Update Implementation
        static private void Update(BusinessEntities proxy)
        {
            try
            {
                Console.WriteLine("### UPDATE ###");
                Console.WriteLine("Enter Invoice ID to update:");
                var ID = Convert.ToInt16(Console.ReadLine());

                //JDO: Get Invoice with selected Invoice ID
                var invoice = (from i in proxy.Invoices.Expand("thirdParty")
                                   where i.ID == ID
                                   select i).Single();

                //JDO: Update values with some example data
                invoice.dateInvoice = DateTime.Now;
                invoice.thirdParty.Name = "UPDATED";
                proxy.UpdateObject(invoice);
                proxy.UpdateObject(invoice.thirdParty);
                proxy.SaveChanges();

                Console.WriteLine("Invoice " + invoice.ID + " was updated.");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Invoice does not exist or wrong character was entered. Description:" + ex.Message);
            }
        }
        #endregion

        #region Delete Implementation
        static private void Delete(BusinessEntities proxy)
        {
            try
            {
                Console.WriteLine("### DELETE ###");
                Console.WriteLine("Enter Invoice ID to delete:");
                var ID = Convert.ToInt16(Console.ReadLine());

                //JDO: Get Invoice with selected Invoice ID
                var invoice = (from i in proxy.Invoices
                                   where i.ID == ID
                                   select i).Single();

                //JDO: Delete Invoice
                proxy.DeleteObject(invoice);
                proxy.SaveChanges();

                Console.WriteLine("Invoice " + ID + " was deleted.");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Invoice does not exist or wrong character was entered. Description:" + ex.Message);
            }
        }
        #endregion
    }
}
